home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 5
/
Skunkware 5.iso
/
src
/
Games
/
xblockbuster
/
xblockbust.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-05-03
|
10KB
|
388 lines
/*
* Xblockbuster should run on any X11 system (bw or color) - MSW
*
*****************************************************************************
* Appearance ONLY shamelessly stolen from the real video game,
* wonderfully written by someone somewhere (I haven't got the foggiest).
*
* Move mouse to move pallet and keep the ball on the stage.
*
* Stages are built from various building blocks, some of which are based on
* recollection from analogous blocks in the video game, others, in particular
* the interesting ones, are new.
*
* The stages can be defined from the ascii map codes using any text editor.
* They must be numbered consecutively from 0 with the total number
* (i.e., one more than the highest number) available in the file nb_stages.
*
* -- Eric Van Gestel (ericvg@cs.kuleuven.ac.be)
*/
#include "xblockbuster.h"
#include <dirent.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <signal.h>
#include "icons/blockbuster.icon"
#include "patchlevel.h"
int timer_active=FALSE, /* has the user started the ball? */
window_active=FALSE; /* is the pointer in the window? */
int time_to_move = 0;
void
time_tick(sig)
int sig;
{
static unsigned short event_count = 0;
time_to_move = 1;
#ifdef INTR_DRAW
if (timer_active && window_active) {
move_balls();
XFlush(display);
}
#endif /*INTR_DRAW*/
}
setup_itimer()
{
struct sigaction catch, devnull;
struct itimerval interval;
/* Catch SIGALARM reliably */
catch.sa_handler = time_tick;
sigemptyset(&catch.sa_mask);
sigaddset(&catch.sa_mask, SIGALRM);
catch.sa_flags = 0;
if (sigaction(SIGALRM, &catch, &devnull) < 0)
perror("sigaction");
/* ... then set the interval timer */
interval.it_value.tv_sec = 0;
interval.it_value.tv_usec = 10000;
interval.it_interval = interval.it_value;
if (setitimer(ITIMER_REAL, &interval, (struct itimerval *)NULL) < 0)
perror("setitimer");
}
void event_handler()
{
XEvent e;
int row,col,sleeptime;
double old_pallet_y;
char keystr[2],str[10];
setup_itimer();
draw_pallet();
while (1) {
#ifndef INTR_DRAW
if (time_to_move && timer_active && window_active) {
time_to_move = 0;
move_balls();
}
// Now, let's wait for an event, or time to move the balls
{
int Xfd;
fd_set fds;
Xfd = ConnectionNumber(display);
FD_ZERO(&fds);
FD_SET(Xfd, &fds);
select(Xfd+1, &fds, &fds, &fds, 0);
}
if (XPending(display))
#endif /*!INTR_DRAW*/
{
/* Event handling (if any events need to be handled) - MSW */
XNextEvent(display, &e);
#ifdef INTR_DRAW
sighold(SIGALRM);
#endif /*INTR_DRAW*/
switch (e.type) {
case ButtonPress:
switch (e.xbutton.button) {
case Button3: /* right mouse button */
/* Clear message area */
XFillRectangle(display, win, gc_erase,
0,0,STAGE_WIDTH_IN_PIXELS, MSG_HEIGHT);
/* redo messages */
XDrawImageString(display, win, gc,
OFFSET_SPEED, font_height*2, stage_name,
strlen(stage_name));
if (score_incr>1) {
sprintf(str,"Bonus x%d",score_incr);
XDrawImageString(display, win, gc,
OFFSET_SCORE, font_height*2, str,
strlen(str));
}
print_balls();
print_score();
show_speeds();
timer_active=TRUE;
move_balls();
break;
case Button2:
draw_pallet(); /* erase old */
pallet_y = (double) (pallet_yI = PALLET_MAX_Y+4);
pallet_row = MAX_ROW - 1;
draw_pallet(); /* draw new */
break;
case Button1:
draw_pallet(); /* erase old */
if (pallet_yI > PALLET_MIN_Y) {
old_pallet_y = pallet_y;
pallet_y = (double) (pallet_yI -=16);
pallet_row--;
/* See if the ball could have been
deflected as the pallete moved
upwards */
check_deflections(old_pallet_y);
}
draw_pallet(); /* draw new */
break;
}
break;
case KeyPress:
XLookupString((XKeyEvent*) &e,keystr,2, NULL, NULL);
if (keystr[0]==27) { /* Escape to save */
if (!ball1.quadrant && !ball2.quadrant &&
!ball3.quadrant && last_busted_brick==NULL) {
XDrawImageString(display, win, gc,
OFFSET_BALLS, font_height,
"Saving... ",
23);
save();
}
else
XDrawImageString(display, win, gc,
OFFSET_BALLS, font_height,
"Not Saved... ",
23);
}
break;
case MotionNotify:
draw_pallet(); /* erase old pallet */
pallet_x = (double) (pallet_xI =e.xmotion.x);
mouse_yI = e.xmotion.y;
draw_pallet(); /* draw new one */
break;
case EnterNotify:
window_active = TRUE;
break;
case LeaveNotify:
window_active = FALSE;
break;
case Expose:
/* redraw the stage */
for ( row = 0; row <= MAX_ROW; row++ ) {
draw_brick0( row, 0 );
for ( col = 1; col < MAX_COL; col++ )
draw_brick( row, col );
draw_brick0( row, MAX_COL );
}
draw_pallet();
break;
default:
printf("unknown event: %d\n",e.type);
break;
}
#ifdef INTR_DRAW
XFlush(display);
sigrelse(SIGALRM);
#endif /*INTR_DRAW*/
}
}
}
void get_playground( argc, argv )
int argc;
char *argv[];
{
DIR *dirp;
struct dirent *dp;
struct stat st;
int len, found;
/* set default playground directory */
strcpy( playground, STAGEDIR );
strcat( playground, "/" );
/* check for additional arguments (specific playground) */
if ( argc > 1 ) {
if ( argv[1][0] == '-' ) {
/* list available playgrounds */
printf( "available playgrounds are:\n" );
printf( "\tdefault\n" );
dirp = opendir(STAGEDIR);
for( dp=readdir( dirp ); dp!=NULL; dp=readdir( dirp ) ) {
if ( !strncmp( dp->d_name, "STAGES.", 7 ) )
printf( "\t%s\n", (dp->d_name)+7 );
}
closedir( dirp );
exit( 0 );
}
/* it's a playground name or private directory */
if( !strcmp( argv[1], "default" ) ) {
/* just in case someone used default */
strcat( playground, "STAGES" );
return;
}
found = 0;
len = strlen( argv[1] );
dirp = opendir( STAGEDIR );
for( dp=readdir( dirp ); dp!=NULL; dp=readdir( dirp ) ) {
if ( dp->d_reclen == len+7 &&
!strcmp( (dp->d_name)+7, argv[1] ) ) {
found++;
break;
}
}
closedir( dirp );
if ( found )
strcat( playground, dp->d_name );
else {
/* private dir */
strcpy( playground, argv[1] );
stat( playground, &st );
if( !(st.st_mode & S_IFDIR) ) {
printf( "private playground <%s> not a directory.\n",
playground );
exit( 1 );
}
}
} else {
strcat( playground, "STAGES" );
}
}
/*** xblockbuster ***/
void main( argc, argv )
int argc;
char *argv[];
{
XGCValues xgcvalues;
Pixmap icon_image;
XSizeHints size_hints;
XWMHints wm_hints;
XClassHint class_hints;
XTextProperty VersionTextProp;
static char *VersionList[2] = { VERSION, 0 };
/* who am i ? ['cuserid(3S)' is fooled by 'su(1)'] */
login = getpwuid( getuid( ) )->pw_name;
if ((display=XOpenDisplay(NULL))==NULL) {
fprintf(stderr, "Unable to open display: %s\n",
XDisplayName(NULL));
exit(1);
}
//(void) XSynchronize(display, 1); // For DEBUGGING
screen_num = DefaultScreen(display);
win = XCreateSimpleWindow(display, RootWindow(display, screen_num),
0, 0, STAGE_WIDTH_IN_PIXELS, STAGE_HEIGHT_IN_PIXELS,
0, 2, WhitePixel(display, screen_num));
XSelectInput(display, win, ExposureMask | ButtonPressMask |
LeaveWindowMask | EnterWindowMask | KeyPressMask |
PointerMotionMask);
if ((font_info = XLoadQueryFont(display, FONT))==NULL) {
fprintf(stderr,"Unable to load font %s\n",FONT);
exit(1);
}
font_width= font_info->max_bounds.rbearing - font_info->min_bounds.lbearing;
font_height=font_info->max_bounds.ascent + font_info->max_bounds.descent +1;
xgcvalues.foreground = BlackPixel(display, screen_num);
xgcvalues.background = WhitePixel(display, screen_num);
xgcvalues.graphics_exposures = False;
xgcvalues.font = font_info->fid;
/* create the various graphic contexts we need. gc and gc_color
differ only in the we only change the colors on the gc_color context,
and thus, it is only used for brick drawing. gc_color really has no
use on a black & white system */
gc = XCreateGC(display, win, GCFont |
GCForeground | GCBackground | GCGraphicsExposures, &xgcvalues);
gc_color = XCreateGC(display, win, GCFont |
GCForeground | GCBackground | GCGraphicsExposures, &xgcvalues);
xgcvalues.function = GXclear;
gc_erase = XCreateGC(display, win, GCForeground | GCBackground |
GCFont | GCGraphicsExposures | GCFunction, &xgcvalues);
xgcvalues.function = GXxor; /* Exclusive or */
xgcvalues.foreground = WhitePixel(display, screen_num);
xgcvalues.background = BlackPixel(display, screen_num);
gc_xor = XCreateGC(display, win, GCForeground | GCBackground |
GCFont | GCGraphicsExposures | GCFunction, &xgcvalues);
/* Create our icon for when the window is closed */
if (!(icon_image = XCreateBitmapFromData(display, win,
blockbuster_bits,blockbuster_width, blockbuster_height)))
{
fprintf(stderr, "Can't create icon pixmap\n");
exit (1);
}
size_hints.flags = PMinSize;
size_hints.x = 0;
size_hints.y = 0;
size_hints.height = STAGE_HEIGHT_IN_PIXELS;
size_hints.min_height = STAGE_HEIGHT_IN_PIXELS;
size_hints.width = STAGE_WIDTH_IN_PIXELS;
size_hints.min_width = STAGE_WIDTH_IN_PIXELS;
wm_hints.flags = InputHint | IconPixmapHint;
wm_hints.input = True;
wm_hints.icon_pixmap = icon_image;
class_hints.res_name = "XBlockbuster";
class_hints.res_class = "XBlockbuster";
XStringListToTextProperty(VersionList, 1, &VersionTextProp);
XSetWMProperties(display, win, &VersionTextProp, &VersionTextProp,
argv,argc, &size_hints, &wm_hints, &class_hints);
XMapWindow(display, win);
/* initialize random (used to determine next stage_nb) */
srand48( time( 0 ) );
get_playground( argc, argv );
/* and off we go */
bricks_init();
ball_init();
start_up( );
ball1.quadrant = ball2.quadrant = ball3.quadrant = 0;
event_handler();
}